package test.SoundDriver;

import java.util.HashMap;
import java.util.Stack;

public class Match {
	private int matchMode;
	private Template templetes;
	
	public Match() {
		matchMode = -1;
		templetes = new Template();
	}
	
	public int getMatchMode(){
		return matchMode;
	}
	
	public void calMatchMode(float[] curMove){
		HashMap map = templetes.get();
		float minDis = 0;
		float curDis;
		int mode = -1;
		for(int i=0; i<map.size(); i++){
			curDis = dtw(curMove, (float[]) map.get(i));
			if(curDis<minDis){
				mode = i;
				minDis = curDis;
			}
		}
		matchMode = mode;
	}
	
	public static float dtw(float[] a, float[] b) {
		// a,b - the sequences, dw - the minimal distances matrix
		// w - the warping path
		int n = a.length, m = b.length;
		float[][] d = new float[n][m]; // the euclidian distances matrix
		float[][] dw = new float[n][m];
		for (int i = 0; i < n; i++)
			for (int j = 0; j < m; j++)
				d[i][j] = Math.abs(a[i] - b[j]);
		// determinate of minimal distance
		dw[0][0] = d[0][0];
		for (int i = 1; i < n; i++)
			dw[i][0] = d[i][0] + dw[i - 1][0];
		for (int j = 1; j < m; j++)
			dw[0][j] = d[0][j] + dw[0][j - 1];
		for (int i = 1; i < n; i++)
			for (int j = 1; j < m; j++)
				if (dw[i - 1][j - 1] <= dw[i - 1][j])
					if (dw[i - 1][j - 1] <= dw[i][j - 1])
						dw[i][j] = d[i][j] + dw[i - 1][j - 1];
					else
						dw[i][j] = d[i][j] + dw[i][j - 1];
				else if (dw[i - 1][j] <= dw[i][j - 1])
					dw[i][j] = d[i][j] + dw[i - 1][j];
				else
					dw[i][j] = d[i][j] + dw[i][j - 1];
		int i = n - 1, j = m - 1;
		float element = dw[i][j];
		// determinate of warping path
		float pathDistance = element;
		do {
			if (i > 0 && j > 0)
				if (dw[i - 1][j - 1] <= dw[i - 1][j])
					if (dw[i - 1][j - 1] <= dw[i][j - 1]) {
						i--;
						j--;
					} else
						j--;
				else if (dw[i - 1][j] <= dw[i][j - 1])
					i--;
				else
					j--;
			else if (i == 0)
				j--;
			else
				i--;
			pathDistance += dw[i][j];
		} while (i != 0 || j != 0);
		return pathDistance;
	}

}
